/*
 * PhotonRTOS础光实时操作系统 -- AUTOSAR调度表内部实现
 *
 * Copyright (C) 2022, 2023 国科础石(重庆)软件有限公司
 *
 * 作者: Lin Yang <s-yanglin@kernelsoft.com>
 *
 * License terms: GNU General Public License (GPL) version 3
 *
 */

#ifndef OS_AUTOSAR_SCHEDULE_TABLE_INTERNAL_H
#define OS_AUTOSAR_SCHEDULE_TABLE_INTERNAL_H

#include <autosar/common.h>
#include <autosar/schedule_table.h>
#include <autosar/counter_internal.h>
#include <autosar/event_internal.h>
#include <autosar/calllevel_internal.h>


typedef VAR(struct autosar_schedule_table, TYPEDEF) OsScheduleTableType;
typedef P2VAR(OsScheduleTableType, TYPEDEF, OS_APPL_DATA) OsScheduleTableRefType;
typedef VAR(struct autosar_expiry_point, TYPEDEF) OsExpiryPointType;
typedef P2VAR(OsExpiryPointType, TYPEDEF, OS_APPL_DATA) OsExpiryPointRefType;
typedef VAR(uint8, TYPEDEF) OsExpiryPointIdType;
typedef VAR(uint8, TYPEDEF) OsScheduleTableSyncType;
typedef VAR(struct autosar_expiry_point_task, TYPEDEF) OsExpiryPointTaskType;
typedef P2VAR(OsExpiryPointTaskType, TYPEDEF, OS_APPL_DATA) OsExpiryPointTaskRefType;
typedef VAR(struct autosar_expiry_point_event, TYPEDEF) OsExpiryPointEventType;
typedef P2VAR(OsExpiryPointEventType, TYPEDEF, OS_APPL_DATA) OsExpiryPointEventRefType;


#define NO_SYNC		((OsScheduleTableSyncType)0x0)
#define EXPLICIT	((OsScheduleTableSyncType)0x1)
#define EXPLICIT_ASYNC	((OsScheduleTableSyncType)0x1)
#define EXPLICIT_SYNC	((OsScheduleTableSyncType)0x3)
#define IMPLICIT_SYNC	((OsScheduleTableSyncType)0x4)
#define SYNC_MASK	((OsScheduleTableSyncType)~0x2)


/**
 * [SWS_Os_00409] ⌈操作系统模块的调度表应由一个计数器驱动。 ⌋ ( )
 * [SWS_Os_00413] ⌈调度表应可配置为单次或重复。 ⌋ ( )
 * [SWS_Os_00438] ⌈调度表应定义一个精度界限，其值在 0 到持
 * 续时间的范围内。 ⌋ ( )
 */
/**
 * 调度表的数据结构：
 * object:	必须放在结构体的首部，代表schedule_table的父类
 * waiter:	调度表的等待者，用于驱动调度表
 * counterID:	驱动调度表的计数器
 * expirypts:	调度表的到期点链表
 * next_pt:	调度表下一个待处理的到期点
 * duration:	调度表的持续时间
 * cycle:	调度表的循环周期，0表示不循环，正常循环应等于duration
 * status:	调度表的状态
 * next_schedtblID:	结束后需要激活的下一个调度表
 * sync:	调度表的同步策略
 * deviation:	调度表与同步计数器的偏差
 * precision:	调度表的同步的精度
 * lock:	保护调度表部分数据的锁，自旋锁
 */
struct autosar_schedule_table {
	VAR(OsObjectType, TYPEDEF) object;
	VAR(OsWaiterType, TYPEDEF) waiter;
	VAR(CounterType, TYPEDEF) counterID;
	VAR(OsListType, TYPEDEF) expriypts;
	P2VAR(OsExpiryPointType, TYPEDEF, OS_APPL_DATA) next_pt;
	VAR(TickType, TYPEDEF) duration;
	VAR(TickType, TYPEDEF) cycle;
	VAR(ScheduleTableStatusType, TYPEDEF) status;
	VAR(ScheduleTableType, TYPEDEF) next_schedtblID;
#if defined(AUTOSAR_SYNCHRONIZATION_SUPPORT)
	VAR(OsScheduleTableSyncType, TYPEDEF) sync;
	VAR(int32, TYPEDEF) deviation;
	VAR(TickType, TYPEDEF) precision;
#endif /* defined(AUTOSAR_SYNCHRONIZATION_SUPPORT) */
	VAR(OsSpinLockType, TYPEDEF) lock;
};


/**
 * [SWS_Os_00402] ⌈到期点应包含一组（可能为空）要激活的任务。 ⌋ ( )
 * [SWS_Os_00403] ⌈到期点应包含一组（可能为空）要设置的事件。 ⌋ ( )
 * [SWS_Os_00404] ⌈到期点应包含从调度表开始的刻度偏移量。 ⌋ ( )
 * [SWS_Os_00415] ⌈到期点应允许配置OsScheduleTableMaxShorten ，
 *		该配置定义可从到期点偏移量中减去的最大tick数。 ⌋ ( )
 * [SWS_Os_00416] ⌈到期点应允许配置OsScheduleTableMaxLengthen ，
 *		该配置定义可添加到到期点偏移量的最大tick数。 ⌋ ( )
 */

struct autosar_expiry_point {
	VAR(TickType, TYPEDEF) time;
	VAR(ScheduleTableType, TYPEDEF) schedule_tableID;
	VAR(OsListType, TYPEDEF) list;
#if defined(AUTOSAR_SYNCHRONIZATION_SUPPORT)
	VAR(TickType, TYPEDEF) max_shorten;
	VAR(TickType, TYPEDEF) max_lengthen;
#endif /* defined(AUTOSAR_SYNCHRONIZATION_SUPPORT) */
	VAR(OsListType, TYPEDEF) tasks;
	VAR(OsListType, TYPEDEF) events;
};

struct autosar_expiry_point_task {
	VAR(TaskType, TYPEDEF) taskID;
	VAR(OsListType, TYPEDEF) list;
};

struct autosar_expiry_point_event {
	VAR(TaskType, TYPEDEF) taskID;
	VAR(EventMaskType, TYPEDEF) event;
	VAR(OsListType, TYPEDEF) list;
};


extern VAR(OsScheduleTableType, AUTOMATIC)
	autosar_schedule_tables[AUTOSAR_NR_SCHEDULE_TABLE];

extern VAR(OsExpiryPointType, AUTOMATIC)
	autosar_expiry_points[AUTOSAR_NR_EXPIRY_POINT];

extern VAR(OsExpiryPointTaskType, AUTOMATIC)
	autosar_expiry_point_tasks[AUTOSAR_NR_EXPIRY_POINT_TASK];

extern VAR(OsExpiryPointEventType, AUTOMATIC)
	autosar_expiry_point_events[AUTOSAR_NR_EXPIRY_POINT_EVENT];

/* 暂停调度表的实际实现 */
FUNC(StatusType, OS_CODE) __stop_schedule_table(
	VAR(ScheduleTableType, AUTOMATIC) ScheduleTableID);

/* 在相对时刻开始调度表的实际实现 */
FUNC(StatusType, OS_CODE) __start_schedule_table_rel(
	VAR(ScheduleTableType, AUTOMATIC) ScheduleTableID,
	VAR(TickType, AUTOMATIC) Offset);

/* 获取调度表的下一个到期点 */
FUNC(OsExpiryPointRefType, OS_CODE) __get_next_expiry_point(
	VAR(OsScheduleTableRefType, AUTOMATIC) schedule_table_ref);

/* 获取调度表下一节点到下下节点的位移，已经同步调整的值 */
FUNC(TickType, OS_CODE) __offset_next_2_expiry_point(
	VAR(OsScheduleTableRefType, AUTOMATIC) schedule_table_ref);

/**
 * 调度表的回调函数，
 * 在此函数中处理到期表的事务并调用当前到期点的回调函数
 */
FUNC(void, OS_CODE) schedule_table_callback(
	VAR(OsWaiterRefType, AUTOMATIC) waiter_ref);

/* 在绝对时刻开始调度表 */
FUNC(void, OS_CODE) __start_schedule_table_abs(
	VAR(ScheduleTableType, AUTOMATIC) ScheduleTableID,
	VAR(TickType, AUTOMATIC) Start);


/* 将expiry point 添加到 schedule tabel */
FUNC(StatusType, OS_CODE) __add_expiry_point_to_schedule_table(
	VAR(OsExpiryPointRefType, AUTOMATIC) expiry_point_ref,
	VAR(ScheduleTableType, AUTOMATIC) ScheduleTableID);

/* 将一个调度表绑定到计数器 */
FUNC(StatusType, OS_CODE) bind_schedule_table_to_counter(
	VAR(ScheduleTableType, AUTOMATIC) ScheduleTableID,
	VAR(CounterType, AUTOMATIC) CounterID);

/* 调度表的到期点的回调函数 */
FUNC(void, OS_CODE) expiry_point_callback(
	VAR(OsExpiryPointRefType, AUTOMATIC) expiry_point_ref);

/* 根据expiry_point指针获取expiry_point id，
 * 返回 AUTOSAR_NR_EXPIRY_POINT 表示指针无效 */
FUNC(OsExpiryPointIdType, OS_CODE) get_expiry_point_id(
	VAR(OsExpiryPointRefType, AUTOMATIC) expiry_point_ref);


#endif /* OS_AUTOSAR_SCHEDULE_TABLE_INTERNAL_H */

